/******************************************************************************* 
  Copyright (C), 1988-2020, zeno Tech. Co., Ltd.
  Description:   ring buffer模块  
  Function List:     
  History:
    <wangmc -- 2015-11-19>  创建
*******************************************************************************/ 

/*=============================================================================
                                 Includes                                  
 =============================================================================*/
#include "aacPriv.h"

/*=============================================================================
                               Macro Definition
 =============================================================================*/

/*=============================================================================
                        Local Structures and Typedef 
 =============================================================================*/
/* ring buffer控制结构体 */
typedef struct
{
    unsigned int    baseAddr;       /* ring buffer缓存首地址 */
    unsigned int    totalSize;      /* ring buffer缓存长度 */
    unsigned int    wrOfst;         /* ring buffer写入地址偏移 */
    unsigned int    rdOfst;         /* ring buffer读出地址偏移 */
    unsigned int    blockNum;       /* ring buffer有效数据块个数，用于检测  */
    pthread_mutex_t mutexLock;      /* ring buffer多线程操作操作 */
} RINGBUF_ctl_t;

/*=============================================================================
                             Extern Variables                                  
=============================================================================*/


/*=============================================================================
                             Local Variables                                  
 =============================================================================*/


/*=============================================================================
                             Function Definition                                  
 =============================================================================*/

/*******************************************************************************
  Function:     AUDIO_RingbufInit
  Description:  ring buffer初始化
  Input:        - pInitParam: ring buffer初始化参数
  Output:       无
  Return:       !NULL: ring buffer句柄
                NULL: 操作失败
  Others:       无
*******************************************************************************/
void *AUDIO_RingbufInit(int maxsize)
{
    RINGBUF_ctl_t *pRingBufCtl;
    void *pBuf;

    pRingBufCtl = (RINGBUF_ctl_t *)malloc(sizeof(RINGBUF_ctl_t));
    if (!pRingBufCtl)
    {
        LOG_PrintError("Fail to malloc ring buffer!\n");
        return NULL;
    }

    pBuf = malloc(maxsize);
    if (!pBuf)
    {
        LOG_PrintError("Fail to malloc ring buffer memory!\n");
        goto free_buf;
    }
    
    pRingBufCtl->baseAddr = (unsigned int)pBuf;
    pRingBufCtl->totalSize = maxsize;
    pRingBufCtl->wrOfst = 0;
    pRingBufCtl->rdOfst = 0;
    pRingBufCtl->blockNum = 0;
    
    pthread_mutex_init(&pRingBufCtl->mutexLock, NULL);

    return (void *)pRingBufCtl;

free_buf:
    free(pRingBufCtl);
    return NULL;
}

/*******************************************************************************
  Function:     AUDIO_RingbufDeInit
  Description:  注销ring buffer
  Input:        - hRingBuf: ring buffer句柄
  Output:       无
  Return:       0: 操作成功
                -1: 操作失败
  Others:       无
*******************************************************************************/
int AUDIO_RingbufDeInit(void *hRingBuf)
{
    RINGBUF_ctl_t *pRingBufCtl;
    
    pRingBufCtl = (RINGBUF_ctl_t *)hRingBuf;

    pthread_mutex_destroy(&pRingBufCtl->mutexLock);

    free((void *)pRingBufCtl->baseAddr);
    
    free(pRingBufCtl);
    
    return 0;
}

/*******************************************************************************
  Function:     AUDIO_RingbufGet
  Description:  获取ring buffer缓存
  Input:        - hRingBuf: ring buffer句柄
                - size: 申请的缓存长度
  Output:       - pBlockBuf: ring buffer缓存
  Return:       0: 操作成功
                -1: 操作失败
  Others:       无
*******************************************************************************/
int AUDIO_RingbufGet(void *hRingBuf, 
                unsigned int size,
                RINGBUF_block_t *pBlockBuf)
{
    int ret = 0;
    RINGBUF_ctl_t *pRingBufCtl;
    unsigned int ringBufAddr;
    unsigned int ringBufLen;
    
    pRingBufCtl = (RINGBUF_ctl_t *)hRingBuf;

    pthread_mutex_lock(&pRingBufCtl->mutexLock);
    
    if (pRingBufCtl->wrOfst >= pRingBufCtl->rdOfst) 
    {
        ringBufAddr = pRingBufCtl->baseAddr + pRingBufCtl->wrOfst;
        ringBufLen = pRingBufCtl->totalSize - pRingBufCtl->wrOfst;

        if(ringBufLen < size)
        {
            ringBufAddr = pRingBufCtl->baseAddr;
            ringBufLen = pRingBufCtl->rdOfst;

            if (ringBufLen < size)
            {
                ret = -1;
                LOG_PrintInfo("Buffer isn't enough! ringBufLen %d bufSize %d "
                              "baseAddr 0x%x totalSize 0x%x wrOfst 0x%x rdOfst 0x%x, blockNum %d\n",
                              ringBufLen,
                              size,
                              pRingBufCtl->baseAddr,
                              pRingBufCtl->totalSize,
                              pRingBufCtl->wrOfst,
                              pRingBufCtl->rdOfst,
                              pRingBufCtl->blockNum);
                goto unlock_mutex;
            }
            
            pRingBufCtl->wrOfst = size;
        }
        else
        {
            /* pRingBufCtl->wrOfst + bufSize == pRingBufCtl->totalSize时，
               pRingBufCtl->wrOfst = 0 */
            pRingBufCtl->wrOfst = 
                (pRingBufCtl->wrOfst + size)%pRingBufCtl->totalSize;
        }
    }
    else
    {
        ringBufAddr = pRingBufCtl->baseAddr + pRingBufCtl->wrOfst;
        ringBufLen = pRingBufCtl->rdOfst - pRingBufCtl->wrOfst;

        if (ringBufLen < size)
        {
            ret = -1;
            LOG_PrintInfo("Buffer isn't enough! ringBufLen %d bufSize %d "
                          "baseAddr 0x%x totalSize 0x%x wrOfst 0x%x rdOfst 0x%x blockNum %d\n", 
                          ringBufLen,
                          size,
                          pRingBufCtl->baseAddr,
                          pRingBufCtl->totalSize,
                          pRingBufCtl->wrOfst,
                          pRingBufCtl->rdOfst,
                          pRingBufCtl->blockNum);
            goto unlock_mutex;
        }

        /* pRingBufCtl->wrOfst + bufSize == pRingBufCtl->totalSize时，
           pRingBufCtl->wrOfst = 0 */
        pRingBufCtl->wrOfst = 
            (pRingBufCtl->wrOfst + size)%pRingBufCtl->totalSize;
    }

    pRingBufCtl->blockNum++;

    pBlockBuf->bufAddr = ringBufAddr;
    pBlockBuf->bufSize = size;

unlock_mutex:
    pthread_mutex_unlock(&pRingBufCtl->mutexLock);
    return ret;
} 


/*******************************************************************************
  Function:     AUDIO_RingbufPut
  Description:  释放ring buffer缓存
  Input:        - hRingBuf: ring buffer句柄
                - pBlockBuf: ring buffer缓存
  Output:       无
  Return:       0: 操作成功
                -1: 操作失败
  Others:       无
*******************************************************************************/
int AUDIO_RingbufPut(void *hRingBuf, RINGBUF_block_t *pBlockBuf)
{
    int ret = 0;
    RINGBUF_ctl_t *pRingBufCtl;
    unsigned int bufOfst;

    pRingBufCtl = (RINGBUF_ctl_t *)hRingBuf;
    
    pthread_mutex_lock(&pRingBufCtl->mutexLock);

    if (!pRingBufCtl->blockNum)
    {
        LOG_PrintError("The buffer has been released!  bufAddr 0x%x bufSize 0x%x "
                       "baseAddr 0x%x totalSize 0x%x wrOfst 0x%x rdOfst 0x%x blockNum %d\n", 
                       pBlockBuf->bufAddr,
                       pBlockBuf->bufSize,
                       pRingBufCtl->baseAddr,
                       pRingBufCtl->totalSize,
                       pRingBufCtl->wrOfst,
                       pRingBufCtl->rdOfst,
                       pRingBufCtl->blockNum);
        ret = -1;
        goto unlock_mutex;
    }

    bufOfst = pBlockBuf->bufAddr - pRingBufCtl->baseAddr;
    if ((bufOfst != pRingBufCtl->rdOfst)
        && (bufOfst != 0))
    {
        LOG_PrintError("The buffer is invalid! bufAddr 0x%x bufSize 0x%x "
                       "baseAddr 0x%x totalSize 0x%x wrOfst 0x%x rdOfst 0x%x blockNum %d\n",
                       pBlockBuf->bufAddr,
                       pBlockBuf->bufSize,
                       pRingBufCtl->baseAddr,
                       pRingBufCtl->totalSize,
                       pRingBufCtl->wrOfst,
                       pRingBufCtl->rdOfst,
                       pRingBufCtl->blockNum);
        ret = -1;
        goto unlock_mutex;
    }

    pRingBufCtl->rdOfst = 
        (bufOfst + pBlockBuf->bufSize)%pRingBufCtl->totalSize;
    pRingBufCtl->blockNum--;
    
unlock_mutex:
    pthread_mutex_unlock(&pRingBufCtl->mutexLock);
    return ret;
}


/*******************************************************************************
  Function:     AUDIO_RingbufFlush
  Description:  清空ring buffer缓存
  Input:        无
  Output:       无
  Return:       0: 操作成功
                -1: 操作失败
  Others:       无
*******************************************************************************/
int AUDIO_RingbufFlush(void *hRingBuf)
{
    RINGBUF_ctl_t *pRingBufCtl;

    pRingBufCtl = (RINGBUF_ctl_t *)hRingBuf;
    
    pthread_mutex_lock(&pRingBufCtl->mutexLock);

    pRingBufCtl->wrOfst = 0;
    pRingBufCtl->rdOfst = 0;
    pRingBufCtl->blockNum = 0;
    
    pthread_mutex_unlock(&pRingBufCtl->mutexLock);
    
    return 0;
}

